package org.keyczar.rsa;

import org.keyczar.exceptions.KeyczarException;
import org.keyczar.interfaces.SigningStream;
import org.keyczar.interfaces.Stream;
import org.keyczar.interfaces.VerifyingStream;

import java.nio.ByteBuffer;
import java.security.GeneralSecurityException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;

/**
 * {@link Stream} implementation used by {@link RsaPrivateSigningKey}.
 */
class RsaSigningStream implements SigningStream, VerifyingStream {
  protected final Signature signature;
  protected final RSAPrivateKey jcePrivateKey;
  private final VerifyingStream verifyingStream;
  private final int digestSize;
  
  RsaSigningStream(Signature signature, RSAPrivateKey jcePrivateKey, RSAPublicKey jcePublicKey) {
    this.signature = signature;
    this.jcePrivateKey = jcePrivateKey;
    this.verifyingStream = new RsaVerifyingStream(signature, jcePublicKey);
    this.digestSize = jcePublicKey.getModulus().bitLength() / 8;
  }
  
  @Override
  public int digestSize() {
    return digestSize;
  }
 
  @Override
  public void initSign() throws KeyczarException {
    try {
      signature.initSign(jcePrivateKey);
    } catch (GeneralSecurityException e) {
      throw new KeyczarException(e);
    }
  }
  
  @Override
  public void sign(ByteBuffer output) throws KeyczarException {
    try {
      byte[] sig = signature.sign();
      output.put(sig);
    } catch (SignatureException e) {
      throw new KeyczarException(e);
    }
  }
  
  @Override
  public void updateSign(ByteBuffer input) throws KeyczarException {
    try {
      signature.update(input);
    } catch (SignatureException e) {
      throw new KeyczarException(e);
    }
  }

  @Override
  public void initVerify() throws KeyczarException {
    verifyingStream.initVerify();
  }

  @Override
  public void updateVerify(ByteBuffer input) throws KeyczarException {
    verifyingStream.updateVerify(input);
  }

  @Override
  public boolean verify(ByteBuffer signature) throws KeyczarException {
    return verifyingStream.verify(signature);
  }
}
